<?php
/************************************************************************
 Omnitrix - PHP Development Framework
 Copyright (C) 2012-2018 amonest(eastson@outlook.com)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
************************************************************************/

$GLOBALS['_XEVENT'] = array();

function otx_event_listeners($event_name = null)
{
	if (null !== $event_name) {
		if (empty($GLOBALS['_XEVENT'][$event_name])) {
			return array();
		}

		krsort($GLOBALS['_XEVENT'][$event_name]);
		return call_user_func_array('array_merge', $GLOBALS['_XEVENT'][$event_name]);
	}

	$listeners = array();

	foreach (array_keys($GLOBALS['_XEVENT']) as $event_name) {
		krsort($GLOBALS['_XEVENT'][$event_name]);
		$listeners = array_merge($listeners, call_user_func_array('array_merge', $GLOBALS['_XEVENT'][$event_name]));
	}

	return $listeners;
}

function otx_event_register($event_name, $listener, $priority = 0)
{
	if (is_object($event_name)) {
		$object = $event_name;
		$class_methods = get_class_methods($object);
		foreach ($class_methods as $method_name) {
			if (substr($method_name, strlen($method_name) - 6, 6) == '_event') {
				$event_name = substr($method_name, 0, strlen($method_name) - 6);
				otx_event_register($event_name, array($object, $method_name), $priority);
			}
		}
		return;
	}

	$GLOBALS['_XEVENT'][$event_name][$priority][] = $listener;
	krsort($GLOBALS['_XEVENT'][$event_name]);
}

function otx_event_unregister($event_name, $listener)
{
	foreach ($GLOBALS['_XEVENT'][$event_name] as $priority => $listeners) {
		if (false !== ($key = array_search($listener, $listeners))) {
			unset($GLOBALS['_XEVENT'][$event_name][$priority][$key]);
		}
	}
}

function otx_event_dispatch($event_name, $event_args = null)
{
	$default_return = null;

	$listeners = otx_event_listeners($event_name);
	if (empty($listeners)) {
		return $default_return;
	}

	$event_object = new stdClass();
	$event_object->event_name = $event_name;
	$event_object->return_value = $default_return;
	$event_object->is_continued = true;

	foreach ((array) $event_args as $arg_name => $arg_value) {
		$event_object->$arg_name = $arg_value;
	}

	foreach ($listeners as $listener) {
		call_user_func($listener, $event_object);
		if (!$event_object->is_continued) {
			break;
		}
	}

	return $event_object;
}

function otx_event_return($event_name, $params = null)
{
	$event_object = otx_event_dispatch($event_name, $params);
	return $event_object->return_value;
}